#include <streams.h>
#include <initguid.h>

#ifndef __NETSTREAMGUIDS_DEFINED
#define __NETSTREAMGUIDS_DEFINED


// {3C9056DF-D77E-4eb3-BC48-C175C784763B}
DEFINE_GUID(CLSID_NetStreamFilter, 
0x3c9056df, 0xd77e, 0x4eb3, 0xbc, 0x48, 0xc1, 0x75, 0xc7, 0x84, 0x76, 0x3b);


// {5985566C-4E04-4a58-91DE-F8E3F9B939AB}
DEFINE_GUID(IID_INetStreamFilterConfig, 
0x5985566c, 0x4e04, 0x4a58, 0x91, 0xde, 0xf8, 0xe3, 0xf9, 0xb9, 0x39, 0xab);


// {37A11A90-52E1-4771-B360-83481308E605}
DEFINE_GUID(IID_INetStreamFilterCB, 
0x37a11a90, 0x52e1, 0x4771, 0xb3, 0x60, 0x83, 0x48, 0x13, 0x8, 0xe6, 0x5);


#endif


#define g_wszNetStream     L"NetStream Filter"
typedef struct _Packet
{
	BYTE* pData;
	long nBytes;
	long StartTime;
	long EndTime;
}Packet;

DECLARE_INTERFACE_(INetStreamFilterCB, IUnknown)
{
    STDMETHOD(CheckMediaType)(THIS_ const AM_MEDIA_TYPE *amt) PURE;
    STDMETHOD(GetMediaType)(THIS_ int lPosition, const AM_MEDIA_TYPE *amt) PURE;
    STDMETHOD(OnMediaTypeChanged)(THIS_ int hr, const AM_MEDIA_TYPE *amt) PURE;
	STDMETHOD(OnDecideBufferSize)(THIS_ IMemAllocator* pAlloc,ALLOCATOR_PROPERTIES *pRequest) PURE;
	STDMETHOD(OnSetPinAllocator)(THIS_ IMemAllocator* pAllocator)PURE;
	STDMETHOD(OnDeliverSample)(THIS_ IMediaSample* pSample)PURE;
	STDMETHOD(Notify)(THIS_ IBaseFilter* pSelf,Quality q)PURE;
};

DECLARE_INTERFACE_(INetStreamFilterConfig, IUnknown) 
{
    STDMETHOD(SetPinMediaType) (THIS_ const AM_MEDIA_TYPE *amt) PURE;
    STDMETHOD(SetCallback) (THIS_ INetStreamFilterCB *pfn) PURE;
    STDMETHOD(DeliverPacket)(THIS_ const long StartTime,const long EndTime) PURE;
	STDMETHOD(SetPinAllocator)(THIS_)PURE;
};

class COutputPin;


class AM_NOVTABLE CNetStreamFilterConfig : public INetStreamFilterConfig, public CUnknown
{
	public:
		DECLARE_IUNKNOWN
		CNetStreamFilterConfig(__in_opt LPCTSTR pName, __in_opt LPUNKNOWN pUnk) : CUnknown(pName, pUnk) {}
};

class MediaPacket : public IMediaSample
{
	MediaPacket(){}
};

class COutputPin : public CBaseOutputPin, public CNetStreamFilterConfig
{

public:
	INetStreamFilterCB* m_Callback;
protected:
	CMediaType m_amt;
	CCritSec m_crtPinLock ; 
	IPin* pReceiver;
public:
	COutputPin(IN  TCHAR* szName,IN CBaseFilter* pFilter,IN  CCritSec* pLock,OUT HRESULT* pHr,IN  LPCWSTR pszName);
	~COutputPin(){}
	HRESULT GetMediaType(int lPosition,CMediaType *pMediaType);
	HRESULT CheckMediaType(const CMediaType* pmt);
	HRESULT Active();
	HRESULT Inactive();
	HRESULT DecideBufferSize(IMemAllocator* pAlloc, ALLOCATOR_PROPERTIES* pRequest);
	STDMETHODIMP Notify(IBaseFilter *pSelf,Quality q)
	{
		m_Callback->Notify(pSelf,q);
		return S_OK;
	}
    STDMETHODIMP DeliverPacket(const long StartTime,const long EndTime);
    STDMETHODIMP SetPinMediaType(const AM_MEDIA_TYPE *amt);
    STDMETHODIMP SetCallback(INetStreamFilterCB *pfn);
	STDMETHODIMP SetPinAllocator();
	HRESULT CompleteConnect(IPin *pReceivePin);
	void LockPin(){m_crtPinLock.Lock ();}
    void UnlockPin(){m_crtPinLock.Unlock();}
	STDMETHODIMP NonDelegatingQueryInterface(REFIID riid,void** ppv);
};

class CNetStream : public CBaseFilter
{

protected:
	COutputPin* m_pVideoOutput;
	COutputPin* m_pAudioOutput;
	CCritSec m_crtFilterLock ; 

public :

    CNetStream(IN TCHAR* tszName,IN LPUNKNOWN punk,OUT HRESULT* phr);
	~CNetStream()
	{
		delete m_pVideoOutput;
		delete m_pAudioOutput;
	}
	void LockFilter(){m_crtFilterLock.Lock ();}
    void UnlockFilter(){m_crtFilterLock.Unlock();}
	int GetPinCount(){return 2 ;}
	CBasePin* GetPin(int Index);
    static CUnknown* CreateInstance (LPUNKNOWN punk,HRESULT* phr);
};

